const { EventEmitter } = require('events')

/**
 * 仓位管理器
 *
 * 负责计算和管理交易仓位大小
 * 基于风险评估、信号强度、账户状态等因素综合计算
 */
class PositionManager extends EventEmitter {
  constructor (config = {}) {
    super()

    this.config = {
      // 基础配置
      basePositionSize: 0.1, // 基础仓位大小（占总资金比例）
      maxPositionSize: 0.4, // 最大单一仓位
      maxTotalPosition: 0.8, // 最大总仓位

      // 风险控制
      riskAdjustments: {
        LOW: 1.0,
        MEDIUM: 0.8,
        HIGH: 0.5,
        EXTREME: 0.2
      },

      // 波动率调整
      volatilityAdjustments: {
        low: { threshold: 0.02, multiplier: 1.2 },
        medium: { threshold: 0.05, multiplier: 1.0 },
        high: { threshold: 0.08, multiplier: 0.7 },
        extreme: { threshold: 0.12, multiplier: 0.4 }
      },

      // 信号级别调整
      signalLevelMultipliers: {
        0: 0.6,
        1: 0.8,
        2: 1.0
      },

      // 置信度调整
      confidenceMultipliers: {
        threshold: 0.3,
        minMultiplier: 0.3,
        maxMultiplier: 1.2
      },

      // 账户状态调整
      accountAdjustments: {
        profitFactor: 0.1, // 盈利状态加成
        lossFactor: -0.15, // 亏损状态减成
        drawdownThreshold: 0.1, // 回撤阈值
        drawdownPenalty: 0.5 // 回撤惩罚倍数
      },

      ...config
    }

    // 风险管理器
    this.riskManager = new RiskManager(this.config.riskManager || {})

    // 仓位统计
    this.positionStats = {
      totalCalculations: 0,
      averagePosition: 0,
      maxPositionUsed: 0,
      riskDistribution: {},
      signalLevelDistribution: {}
    }

    this.emit('initialized', { config: this.config })
  }

  /**
   * 计算仓位大小
   * @param {Object} signal 交易信号
   * @param {Object} marketConditions 市场条件
   * @param {Object} accountInfo 账户信息
   * @returns {Object} 仓位信息
   */
  calculatePosition (signal, marketConditions, accountInfo) {
    try {
      // 基础验证
      this.validateInputs(signal, marketConditions, accountInfo)

      // 获取基础仓位
      const basePosition = this.getBasePosition(signal, accountInfo)

      // 风险评估
      const riskLevel = this.riskManager.assessRisk(marketConditions, accountInfo)

      // 各种调整因子
      const adjustments = this.calculateAdjustments(signal, marketConditions, accountInfo, riskLevel)

      // 计算最终仓位
      let finalPosition = basePosition
      Object.values(adjustments).forEach(adjustment => {
        finalPosition *= adjustment.multiplier
      })

      // 应用限制
      finalPosition = this.applyPositionLimits(finalPosition, accountInfo)

      // 更新统计
      this.updateStatistics(finalPosition, riskLevel, signal.level)

      const positionInfo = {
        size: finalPosition,
        sizeUSDT: finalPosition * (accountInfo.totalBalance || 0),
        risk: riskLevel,
        confidence: signal.confidence || 0.5,
        maxDrawdown: this.calculateMaxDrawdown(finalPosition, riskLevel),
        expectedReturn: this.calculateExpectedReturn(finalPosition, signal.confidence, riskLevel),
        stopLoss: this.calculateStopLoss(signal, riskLevel),
        takeProfit: this.calculateTakeProfit(signal, riskLevel),
        adjustments,
        explanation: this.generateExplanation(signal, adjustments, riskLevel)
      }

      this.emit('positionCalculated', {
        signal: signal.reason,
        position: positionInfo
      })

      return positionInfo
    } catch (error) {
      this.emit('calculationError', {
        error: error.message,
        signal: signal?.reason,
        marketConditions
      })
      throw error
    }
  }

  /**
   * 获取基础仓位
   * @private
   */
  getBasePosition (signal, accountInfo) {
    // 从信号中获取建议仓位比例
    let basePosition = signal.positionRate || this.config.basePositionSize

    // 如果信号提供了具体的仓位建议，使用信号的建议
    if (signal.positionRate && signal.positionRate > 0) {
      basePosition = signal.positionRate
    }

    // 确保基础仓位在合理范围内
    return Math.min(Math.max(basePosition, 0.01), this.config.maxPositionSize)
  }

  /**
   * 计算各种调整因子
   * @private
   */
  calculateAdjustments (signal, marketConditions, accountInfo, riskLevel) {
    const adjustments = {}

    // 风险调整
    adjustments.risk = {
      multiplier: this.config.riskAdjustments[riskLevel] || 0.5,
      reason: `风险等级${riskLevel}调整`
    }

    // 置信度调整
    adjustments.confidence = this.calculateConfidenceAdjustment(signal.confidence)

    // 信号级别调整
    adjustments.signalLevel = {
      multiplier: this.config.signalLevelMultipliers[signal.level] || 0.6,
      reason: `信号级别${signal.level}调整`
    }

    // 波动率调整
    adjustments.volatility = this.calculateVolatilityAdjustment(marketConditions)

    // 账户状态调整
    adjustments.account = this.calculateAccountAdjustment(accountInfo)

    // 市场环境调整
    adjustments.market = this.calculateMarketAdjustment(marketConditions)

    return adjustments
  }

  /**
   * 计算置信度调整
   * @private
   */
  calculateConfidenceAdjustment (confidence) {
    const { threshold, minMultiplier, maxMultiplier } = this.config.confidenceMultipliers

    if (confidence < threshold) {
      return {
        multiplier: minMultiplier,
        reason: `置信度过低(${confidence.toFixed(2)})`
      }
    }

    // 线性映射 threshold -> 1.0, 1.0 -> maxMultiplier
    const normalizedConfidence = (confidence - threshold) / (1.0 - threshold)
    const multiplier = 1.0 + (normalizedConfidence * (maxMultiplier - 1.0))

    return {
      multiplier: Math.min(multiplier, maxMultiplier),
      reason: `置信度调整(${confidence.toFixed(2)})`
    }
  }

  /**
   * 计算波动率调整
   * @private
   */
  calculateVolatilityAdjustment (marketConditions) {
    const volatility = marketConditions.volatility || 0.03
    const { volatilityAdjustments } = this.config

    let selectedAdjustment = volatilityAdjustments.medium // 默认

    for (const [level, config] of Object.entries(volatilityAdjustments)) {
      if (volatility >= config.threshold) {
        selectedAdjustment = config
      } else {
        break
      }
    }

    return {
      multiplier: selectedAdjustment.multiplier,
      reason: `波动率调整(${(volatility * 100).toFixed(1)}%)`
    }
  }

  /**
   * 计算账户状态调整
   * @private
   */
  calculateAccountAdjustment (accountInfo) {
    const { profitFactor, lossFactor, drawdownThreshold, drawdownPenalty } = this.config.accountAdjustments

    let multiplier = 1.0
    let reason = '账户状态正常'

    // 盈亏状态调整
    if (accountInfo.unrealizedPnl) {
      if (accountInfo.unrealizedPnl > 0) {
        multiplier += profitFactor
        reason = '盈利状态加成'
      } else {
        multiplier += lossFactor
        reason = '亏损状态减成'
      }
    }

    // 回撤调整
    if (accountInfo.maxDrawdown && accountInfo.maxDrawdown > drawdownThreshold) {
      multiplier *= drawdownPenalty
      reason += ` + 回撤惩罚(${(accountInfo.maxDrawdown * 100).toFixed(1)}%)`
    }

    return {
      multiplier: Math.max(multiplier, 0.1), // 最小不低于0.1
      reason
    }
  }

  /**
   * 计算市场环境调整
   * @private
   */
  calculateMarketAdjustment (marketConditions) {
    let multiplier = 1.0
    const reasons = []

    // 市场混乱调整
    if (marketConditions.isMarketChaos) {
      multiplier *= 0.6
      reasons.push('市场混乱')
    }

    // 流动性调整
    if (marketConditions.liquidity && marketConditions.liquidity < 0.8) {
      multiplier *= 0.8
      reasons.push('流动性不足')
    }

    // 趋势明确性调整
    if (marketConditions.trendClarity === 'HIGH') {
      multiplier *= 1.1
      reasons.push('趋势明确')
    } else if (marketConditions.trendClarity === 'LOW') {
      multiplier *= 0.9
      reasons.push('趋势不明')
    }

    return {
      multiplier,
      reason: reasons.length > 0 ? reasons.join(' + ') : '市场环境正常'
    }
  }

  /**
   * 应用仓位限制
   * @private
   */
  applyPositionLimits (position, accountInfo) {
    // 单一仓位限制
    position = Math.min(position, this.config.maxPositionSize)

    // 总仓位限制
    const currentTotalPosition = accountInfo.totalPosition || 0
    const availablePosition = this.config.maxTotalPosition - currentTotalPosition
    position = Math.min(position, Math.max(availablePosition, 0))

    // 最小仓位限制
    if (position < 0.01) {
      position = 0
    }

    return position
  }

  /**
   * 计算最大回撤
   * @private
   */
  calculateMaxDrawdown (position, riskLevel) {
    const baseDrawdown = position * 0.1 // 基础回撤为仓位的10%

    const riskMultipliers = {
      LOW: 0.8,
      MEDIUM: 1.0,
      HIGH: 1.3,
      EXTREME: 1.8
    }

    return baseDrawdown * (riskMultipliers[riskLevel] || 1.0)
  }

  /**
   * 计算预期收益
   * @private
   */
  calculateExpectedReturn (position, confidence, riskLevel) {
    const baseReturn = position * 0.05 // 基础预期收益5%

    // 置信度调整
    const confidenceMultiplier = 0.5 + confidence

    // 风险调整
    const riskMultipliers = {
      LOW: 0.8,
      MEDIUM: 1.0,
      HIGH: 1.2,
      EXTREME: 0.6
    }

    return baseReturn * confidenceMultiplier * (riskMultipliers[riskLevel] || 1.0)
  }

  /**
   * 计算止损价格
   * @private
   */
  calculateStopLoss (signal, riskLevel) {
    const riskPercentages = {
      LOW: 0.02,
      MEDIUM: 0.03,
      HIGH: 0.05,
      EXTREME: 0.08
    }

    return riskPercentages[riskLevel] || 0.03
  }

  /**
   * 计算止盈价格
   * @private
   */
  calculateTakeProfit (signal, riskLevel) {
    const stopLoss = this.calculateStopLoss(signal, riskLevel)

    // 风险收益比 1:2 到 1:3
    const riskRewardRatios = {
      LOW: 2.5,
      MEDIUM: 2.0,
      HIGH: 1.8,
      EXTREME: 1.5
    }

    return stopLoss * (riskRewardRatios[riskLevel] || 2.0)
  }

  /**
   * 生成说明
   * @private
   */
  generateExplanation (signal, adjustments, riskLevel) {
    const parts = [
      `基础仓位: ${(signal.positionRate || this.config.basePositionSize * 100).toFixed(1)}%`,
      `风险等级: ${riskLevel}`
    ]

    Object.entries(adjustments).forEach(([key, adjustment]) => {
      if (adjustment.multiplier !== 1.0) {
        parts.push(`${adjustment.reason}: x${adjustment.multiplier.toFixed(2)}`)
      }
    })

    return parts.join(', ')
  }

  /**
   * 验证输入参数
   * @private
   */
  validateInputs (signal, marketConditions, accountInfo) {
    if (!signal || typeof signal !== 'object') {
      throw new Error('Invalid signal object')
    }

    if (!marketConditions || typeof marketConditions !== 'object') {
      throw new Error('Invalid marketConditions object')
    }

    if (!accountInfo || typeof accountInfo !== 'object') {
      throw new Error('Invalid accountInfo object')
    }

    if (typeof signal.confidence !== 'number' || signal.confidence < 0 || signal.confidence > 1) {
      throw new Error('Invalid signal confidence: must be between 0 and 1')
    }
  }

  /**
   * 更新统计信息
   * @private
   */
  updateStatistics (position, riskLevel, signalLevel) {
    this.positionStats.totalCalculations++

    // 更新平均仓位
    const currentAvg = this.positionStats.averagePosition
    const count = this.positionStats.totalCalculations
    this.positionStats.averagePosition = (currentAvg * (count - 1) + position) / count

    // 更新最大仓位
    if (position > this.positionStats.maxPositionUsed) {
      this.positionStats.maxPositionUsed = position
    }

    // 更新风险分布
    this.positionStats.riskDistribution[riskLevel] =
      (this.positionStats.riskDistribution[riskLevel] || 0) + 1

    // 更新信号级别分布
    this.positionStats.signalLevelDistribution[signalLevel] =
      (this.positionStats.signalLevelDistribution[signalLevel] || 0) + 1
  }

  /**
   * 获取统计信息
   * @returns {Object} 统计信息
   */
  getStatistics () {
    return {
      ...this.positionStats,
      config: {
        basePositionSize: this.config.basePositionSize,
        maxPositionSize: this.config.maxPositionSize,
        maxTotalPosition: this.config.maxTotalPosition
      }
    }
  }

  /**
   * 重置统计信息
   */
  resetStatistics () {
    this.positionStats = {
      totalCalculations: 0,
      averagePosition: 0,
      maxPositionUsed: 0,
      riskDistribution: {},
      signalLevelDistribution: {}
    }

    this.emit('statisticsReset')
  }

  /**
   * 更新配置
   * @param {Object} newConfig 新配置
   */
  updateConfig (newConfig) {
    const oldConfig = { ...this.config }
    this.config = { ...this.config, ...newConfig }

    this.emit('configUpdated', { oldConfig, newConfig: this.config })
  }
}

/**
 * 风险管理器
 */
class RiskManager {
  constructor (config = {}) {
    this.config = {
      volatilityThresholds: {
        low: 0.02,
        medium: 0.05,
        high: 0.08,
        extreme: 0.12
      },
      liquidityThreshold: 0.8,
      chaosMarketPenalty: 30,
      drawdownThresholds: {
        warning: 0.05,
        danger: 0.1,
        critical: 0.2
      },
      ...config
    }
  }

  /**
   * 评估风险等级
   * @param {Object} marketConditions 市场条件
   * @param {Object} accountInfo 账户信息
   * @returns {string} 风险等级
   */
  assessRisk (marketConditions, accountInfo) {
    let riskScore = 0

    // 市场混乱风险
    if (marketConditions.isMarketChaos) {
      riskScore += this.config.chaosMarketPenalty
    }

    // 波动率风险
    const volatility = marketConditions.volatility || 0.03
    if (volatility > this.config.volatilityThresholds.extreme) {
      riskScore += 40
    } else if (volatility > this.config.volatilityThresholds.high) {
      riskScore += 30
    } else if (volatility > this.config.volatilityThresholds.medium) {
      riskScore += 15
    }

    // 流动性风险
    const liquidity = marketConditions.liquidity || 1.0
    if (liquidity < this.config.liquidityThreshold) {
      riskScore += 25
    }

    // 账户回撤风险
    if (accountInfo.maxDrawdown) {
      if (accountInfo.maxDrawdown > this.config.drawdownThresholds.critical) {
        riskScore += 35
      } else if (accountInfo.maxDrawdown > this.config.drawdownThresholds.danger) {
        riskScore += 25
      } else if (accountInfo.maxDrawdown > this.config.drawdownThresholds.warning) {
        riskScore += 15
      }
    }

    // 趋势不确定性风险
    if (!marketConditions.trendConsistency) {
      riskScore += 20
    }

    // 根据总分确定风险等级
    if (riskScore >= 80) return 'EXTREME'
    if (riskScore >= 60) return 'HIGH'
    if (riskScore >= 35) return 'MEDIUM'
    return 'LOW'
  }
}

module.exports = { PositionManager, RiskManager }
